﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace WBoy.WeixinCore
{
    public class WeixinPayHelper
    {



        public readonly string _appId;//应用编号
        public readonly string _mchId;//商户账号
        public readonly string _notifyUrl;
        private readonly string _apiKey;

        /// <summary>
        /// 获取应用编号
        /// </summary>
        public string AppId => _appId;
        /// <summary>
        /// 获取商户账号
        /// </summary>
        public string MchId => _mchId;
        /// <summary>
        /// 获取回调地址
        /// </summary>
        public string NotifyUrl => _notifyUrl;

        /// <summary>
        /// 微信支付授权
        /// 这个就是自己要保管好的私有Key了（切记只能放在自己的后台代码里，不能放在任何可能被看到源代码的客户端程序中）
        /// 每次自己Post数据给API的时候都要用这个key来对所有字段进行签名，生成的签名会放在Sign这个字段，API收到Post数据的时候也会用同样的签名算法对Post过来的数据进行签名和验证
        /// 收到API的返回的时候也要用这个key来对返回的数据算下签名，跟API的Sign数据进行比较，如果值不一致，有可能数据被第三方给篡改
        /// 微信分配的公众号ID（开通公众号之后可以获取到）
        ///  参加地址：https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=3_1
        /// </summary>
        /// <param name="appId">这里需要使用开放平台的appId 或则服务号的appId</param>
        /// <param name="apiKey">商户中心设置的秘钥</param>
        /// <param name="mchId">商户中心的商户ID</param>
        /// <param name="notifyUrl"></param>
        public WeixinPayHelper(string appId, string apiKey, string mchId,string notifyUrl)
        {
            _appId = appId;
            _apiKey = apiKey;
            _mchId = mchId;
            _notifyUrl = notifyUrl;
        }
        private string Md5_UTF8(string sInputString)
        {
            return BitConverter.ToString(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(sInputString))).Replace("-", "");

        }
        
        public string CreateSign(Dictionary<string, string> parameters)
        {

            var list = new List<string>();
            foreach (var m in parameters)
            {
                if (m.Value != null && m.Value.ToString() != string.Empty)
                {
                    list.Add($"{m.Key}={m.Value.ToString()}&");
                }
            }
            list.Sort();
            var sb = new StringBuilder();
            foreach (var item in list)
            {
                sb.Append(item);
            }
            var strParam = sb.ToString().TrimEnd('&');
            var stringSignTemp = $"{strParam}&key={_apiKey}";

            var result = Md5_UTF8(stringSignTemp).ToUpper();
            //debug信息
            return result;
        }
        /// <summary>
        /// 验证签名
        /// </summary>
        /// <param name="dict"></param>
        /// <returns></returns>
        public bool CheckSign(Dictionary<string, string> dict)
        {
            string tmpSign = dict["sign"];
            dict.Remove("sign");
            string localSign = CreateSign(dict);
            return tmpSign.Trim() == localSign.Trim();
        }
        /// <summary>
        /// 转换成XML
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public string ParseXml(Dictionary<string,string> parameters)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<xml>");
            foreach (string key in parameters.Keys)
            {
                string value = parameters[key];
                sb.Append("<" + key + ">" + value + "</" + key + ">");
            }
            sb.Append("</xml>");
            return sb.ToString();
        }

        /// <summary>
        /// xml字符串转换为dictionary
        /// </summary>
        /// <param name="xmlString"></param>
        /// <returns></returns>
        public Dictionary<string, string> XmlToDictionary(string xmlString)
        {
            System.Xml.XmlDocument document = new System.Xml.XmlDocument();
            document.XmlResolver = null;
            document.LoadXml(xmlString);

            Dictionary<string, string> dic = new Dictionary<string, string>();

            var nodes = document.FirstChild.ChildNodes;

            foreach (System.Xml.XmlNode item in nodes)
            {
                dic.Add(item.Name, item.InnerText);
            }
            return dic;
        }
    }
}
